import axios from 'axios'
import storage from './storage'
import store from '../store'
import router from '../router'

// const token = storage.getItem('token')

const config = token => {
  return {
    baseURL: process.env.VUE_APP_SERVER_IP,
    // baseURL: 'http://192.168.1.150:8080/z',
    headers: {
      'Content-Type': 'application/json;charset=UTF-8',
      'Access-Control-Allow-Origin': process.env.VUE_APP_SERVER_IP,
      Authorization: `Bearer ${token}`
    },
    timeout: 30000,
    withCredentials: true,
    responseType: 'json'
  }
}

// const instance = axios.create(config)

// export { instance }

export default function $axios (options) {
  return new Promise((resolve, reject) => {
    const token = storage.getItem('token')
    const instance = axios.create(config(token))
    // request 拦截器
    instance.interceptors.request.use(
      request => {
        // console.log(request)
        // Tip: 1
        // 请求开始的时候可以结合 vuex 开启全屏的 loading 动画
        store.commit('client/setLoading', true)

        // Tip: 2
        // 带上 token , 可以结合 vuex 或者重 localStorage
        // if (store.getters.token) {
        //     request.headers['X-Token'] = getToken() // 让每个请求携带token--['X-Token']为自定义key 请根据实际情况自行修改
        // } else {
        //     // 重定向到登录页面
        // }
        // 结合 vuex 的本地状态 store, 对 get 请求添加上 If-None-Match, 注意 ETag 需要双引号
        // 实现 vuex 持久化到 localStorage 需要进行相应修改
        // get 和 head 都能携带 If-None-Match
        let param = ''
        let part = `${request.baseURL}${request.url}`
        for (let i in request.params) {
          param += `${i}=${request.params[i]}&`
        }
        if (param.length > 0) {
          part = `${request.baseURL}${request.url}?${param.substring(
            0,
            param.length - 1
          )}`
        }
        console.log(part, store.state.client.urlETag[part])
        if (request.method.toLocaleLowerCase() === 'get') {
          request.headers['If-None-Match'] = store.state.client.urlETag[part]
        }

        // Tip: 3
        // 根据请求方法，序列化传来的参数，根据后端需求是否序列化
        if (
          request.method.toLocaleLowerCase() === 'post' ||
          request.method.toLocaleLowerCase() === 'put' ||
          request.method.toLocaleLowerCase() === 'delete'
        ) {
          // request.data = qs.stringify(request.data)
        }
        return request
      },
      error => {
        // 请求错误时做些事(接口错误、超时等)
        // Tip: 4
        // 关闭loadding
        store.commit('client/setLoading', false)
        console.log('request:', error)

        // 1.判断请求超时
        if (
          error.code === 'ECONNABORTED' &&
          error.message.indexOf('timeout') !== -1
        ) {
          console.log(
            '根据你设置的timeout/真的请求超时 判断请求现在超时了，你可以在这里加入超时的处理方案'
          )
          // 例如再重复请求一次
          // return service.request(originalRequest);
        }
        // 2.需要重定向到错误页面
        const errorInfo = error.response
        console.log(errorInfo)
        if (errorInfo) {
          // error =errorInfo.data
          // 页面那边catch的时候就能拿到详细的错误信息,看最下边的Promise.reject
          // 404 403 500 ... 等
          // const errorStatus = errorInfo.status
          /* router.push({
            path: `/error/${errorStatus}`w
          }) */
        }
        // 在调用的那边可以拿到(catch)你想返回的错误信息
        return Promise.reject(error)
      }
    )

    // response 拦截器
    instance.interceptors.response.use(
      response => {
        store.commit('client/setLoading', false)
        console.log(response)
        if (!response.data && !response.request) {
          // @todo 二次拦截的奇怪问题, 将第一次返回的 data 又重新拦截一次
          return response
        }
        let data
        // IE9时response.data是undefined，因此需要使用response.request.responseText(Stringify后的字符串)
        if (response.data === undefined) {
          data = response.request.responseText
        } else {
          data = response.data
        }
        // 将 get 请求进行缓存
        if (response.config.method.toLocaleLowerCase() === 'get') {
          store.commit('client/setUrlETagItem', {
            url: response.request.responseURL,
            ETag: response.headers['etag']
          })
        }

        // 根据返回的code值来做不同的处理（和后端约定）
        /* switch (data.code) {
          case '':
            break
          default:
        } */
        // 若不是正确的返回code，且已经登录，就抛出错误
        // const err = new Error(data.description)

        // err.data = data
        // err.response = response

        // throw err
        return data
      },
      error => {
        store.commit('client/setLoading', false)
        for (let i in error) {
          console.log('error', i, error[i])
        }
        if (error.response) {
          // 发送请求后，服务端返回的响应码不是 2xx
          // console.log(error.response.data)
          // console.log(error.response.status)
          // console.log(error.response.headers)
          if (error.response.status === 304) {
            // 304, data = null
          }
          if (error.response.status === 401) {
            // 判断 401 的就重新登录
            storage.removeItem('token')
            router.replace({
              path: '/login'
            })
            return
          }
          // 判断 405 的提示没有权限访问
          if (error.response.status === 405) {
            router.replace({
              path: '/error/405'
            })
            return
          }
        } else if (error.request) {
          // 发送请求但是没有响应返回
          // console.log(error.request)
        } else {
          // 其他错误
          // console.log('Error', error.message)
        }
        // console.log(error.config)
        if (error && error.response) {
          /* switch (error.response.status) {
            case 400:
              error.message = '请求错误'
              break

            case 401:
              error.message = '未授权，请登录'
              break

            case 403:
              error.message = '拒绝访问'
              break

            case 404:
              error.message = `请求地址出错: ${error.response.config.url}`
              break

            case 408:
              error.message = '请求超时'
              break

            case 500:
              error.message = '服务器内部错误'
              break

            case 501:
              error.message = '服务未实现'
              break

            case 502:
              error.message = '网关错误'
              break

            case 503:
              error.message = '服务不可用'
              break

            case 504:
              error.message = '网关超时'
              break

            case 505:
              error.message = 'HTTP版本不受支持'
              break

            default:
          } */
        }
        console.error('axios handle', error)
        store.commit('client/setLoading', false)
        // 此处我使用的是 element UI 的提示组件
        // Message.error(`ERROR: ${error}`);
        return Promise.reject(error) // 返回接口返回的错误信息
      }
    )

    // 请求处理
    instance(options)
      .then(res => {
        resolve(res)
        return false
      })
      .catch(error => {
        reject(error)
      })
  })
}
